`timescale 1ns / 1ps
/*--------------------------------------------------------------------*\
FileName        : cbb_aclk_switch.v
Author          ：hpy
Email           ：yuan_hp@qq.com
Date            ：2025年05月14日
Description     ：异步时钟切换模块,消除毛刺

1.例化
cbb_aclk_switch u1 ( 
    .i_clk1(),
    .i_clk2(),
    .i_rst_n(),
    .i_sel(),  //时钟选择  1: output i_clk2 ,0: output i_clk1
    .o_clk()  //时钟输出
);

\*--------------------------------------------------------------------*/

module cbb_aclk_switch ( 
    i_clk1       ,   
    i_clk2       ,
    i_rst_n      ,
    i_sel        ,
    o_clk         
);

//input ports

input                    i_clk1                      ;      //input  clock 1;
input                    i_clk2                      ;      //input  clock 2;

input                    i_rst_n                  ;      //system reset, low is active;
input                    i_sel                    ;      //clock selcect signal;
                                                    
//output ports                                      
output                   o_clk                    ;


//reg define 

reg    [1:0]             counter                    ;
                                                    

reg                      i_sel_i_clk1_sync          ;
reg                      i_sel_i_clk1_sync_dly1     ;

reg                      i_sel_i_clk2_sync          ;
reg                      i_sel_i_clk2_sync_dly1     ;

//wire define 
wire                     o_clk                    ;     //output clk

wire                     temp1                      ;     //temp wire
wire                     temp2                      ;     //temp wire
 
wire                     i_clk1_temp                  ;     //i_clk1_temp wire
wire                     i_clk2_temp                  ;     //i_clk2_temp wire

//parameter define 
parameter WIDTH = 8;
parameter SIZE  = 8;

assign temp1 = i_sel & (~i_sel_i_clk2_sync_dly1) ;

always @(posedge i_clk1 or negedge i_rst_n) begin 
    if(!i_rst_n) i_sel_i_clk1_sync <= 1'b0;
    else i_sel_i_clk1_sync  <= temp1;
end

always @(posedge i_clk1 or negedge i_rst_n) begin 
    if(!i_rst_n) i_sel_i_clk1_sync_dly1 <=1'b0;
    else i_sel_i_clk1_sync_dly1  <= i_sel_i_clk1_sync;
end

assign i_clk1_temp = i_clk1 & i_sel_i_clk1_sync_dly1 ;

assign temp2 = (~i_sel) & (~i_sel_i_clk1_sync_dly1) ;

always @(posedge i_clk2 or negedge i_rst_n) begin 
    if(!i_rst_n) i_sel_i_clk2_sync  <= 1'b0;
    else i_sel_i_clk2_sync  <= temp2 ;
end

always @(posedge i_clk2 or negedge i_rst_n) begin 
    if(!i_rst_n) i_sel_i_clk2_sync_dly1 <=1'b0; 
    else i_sel_i_clk2_sync_dly1  <= i_sel_i_clk2_sync;
end

assign i_clk2_temp = i_clk2 & i_sel_i_clk2_sync_dly1 ;


assign o_clk = i_clk1_temp | i_clk2_temp ;

endmodule
//end of RTL code                       